package utils.ipmac;

import java.net.*;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 获取IP地址和mac地址
 *
 * @author microdsy
 * @date 2018年6月8日
 */
public class NetworkInfoUtil {

    public static List<Pattern> NicName = new CopyOnWriteArrayList<>();
	static {
		/**windows*/
		NicName.add(Pattern.compile(".*Intel.*"));
		NicName.add(Pattern.compile(".*Realtek.*"));
		/**Mac*/
		NicName.add(Pattern.compile(".*en(\\d+).*"));
		/*新版Linux*/
		/**
		 * 新版的CentOS 7 开始对于网卡的编号有另外一套规则，网卡的代号与网卡的来源有关
		 *
		 * eno1：代表由主板bios内置的网卡
		 *
		 * ens1:代表有主板bios内置的PCI-E网卡
		 *
		 * enp2s0: PCI-E独立网卡
		 *
		 * eth0：如果以上都不使用，则回到默认的网卡名
		 */
		NicName.add(Pattern.compile(".*enp2s(\\d+).*"));
		NicName.add(Pattern.compile(".*ens(\\d+).*"));
		NicName.add(Pattern.compile(".*eno(\\d+).*"));
        /**旧版Linux*/
        NicName.add(Pattern.compile(".*eth(\\d+).*"));
        /**旧版Linux*/
        NicName.add(Pattern.compile(".*Xen(\\d+).*"));
	}

	public static boolean testPatten(String name){
        for (Pattern nicName : NicName) {
            Matcher matcher = nicName.matcher(name);
            boolean matches = matcher.matches();
            if (matches) {
                return true;
            }
        }
	    return false;
    }

    /**
     * 获取ip地址
     *
     * @return
     */
    public static String getIpAddress() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                } else {
                    Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        ip = addresses.nextElement();
                        if (ip != null && ip instanceof Inet4Address) {
                            return ip.getHostAddress();
                        }
                    }
                }
            }
        } catch (Exception e) {
            // _logger.error("IP地址获取失败", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取mac地址
     * 此方法过滤了虚拟网卡
     *
     * @return
     */
    public static String getMacAddress() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            byte[] mac = null;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                } else {
                    mac = netInterface.getHardwareAddress();
                    if (mac != null) {
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < mac.length; i++) {
                            sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
                        }
                        if (sb.length() > 0) {
                            return sb.toString();
                        }
                    }
                }
            }
        } catch (Exception e) {
            // _logger.error("MAC地址获取失败", e);
            e.printStackTrace();
        }
        return "";
    }


    /**
     * java获取本机ip（排除虚拟机等一些ip）
     *
     * @return
     */
    public static String getRealIP() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                // 去除回环接口，子接口，未运行和接口
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
					System.out.println("skip:netInterface.getName()=>  " + netInterface.getName() + ";       netInterface.getDisplayName()=>  " + netInterface.getDisplayName());
                    continue;
                }
                String displayName = netInterface.getDisplayName();
                System.out.println("netInterface.getDisplayName()=>  " + displayName);
                boolean effective = true;
                for (Pattern nicName : NicName) {
                    Matcher matcher = nicName.matcher(displayName);
                    boolean matches = matcher.matches();
                    if (matches) {
                        effective = false;
                        break;
                    }
                }
                if (effective) {
                    continue;
                }
                Enumeration<InetAddress> addresses = netInterface.getInetAddresses();

                while (addresses.hasMoreElements()) {
                    InetAddress ip = addresses.nextElement();
                    if (ip != null) {
                        // ipv4
                        if (ip instanceof Inet4Address) {
                            System.out.println("ipv4 = " + ip.getHostAddress());
                            String SERVER_IP = ip.getHostAddress();
                            return SERVER_IP;
                        } else if (ip instanceof Inet6Address) {
                            System.out.println("ipv6 = " + ip.getHostAddress());
                        }
                    }
                }
//                break;
            }
        } catch (SocketException e) {
            System.err.println("Error when getting host ip address" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

}
